package xxl.ioc.typedescriptions 
{
	import flash.utils.Dictionary;
	import xxl.ioc.dependencyproviders.IDependencyProvider;
	import xxl.ioc.Injector;
	import xxl.ioc.utils.FunctionApplyUtil;
	import xxl.ioc.utils.IOCInternal;
	
	/**
	 * ...
	 * @author XXL
	 */
	public class MethodInjectionPoint extends InjectionPoint 
	{
		protected var _parameterMappingIDs:Array;
		protected var _requiredParameters:int;
		
		private var _isOptional:Boolean;
		private var _methodName:String;
		
		public function MethodInjectionPoint(methodName:String, parameters:Array, requiredParameters:uint, isOptional:Boolean, injectParameters:Dictionary) 
		{
			_methodName = methodName;
			_parameterMappingIDs = parameters;
			_requiredParameters = requiredParameters;
			_isOptional = isOptional;
			this.injectParameters = injectParameters;
		}
		
		override public function applyInjection(target:Object, targetType:Class, injector:Injector):void 
		{
			const p:Array = gatherParameterValues(target, targetType, injector);
			if (p.length >= _requiredParameters)
			{
				FunctionApplyUtil.Apply(target, _methodName, p);
			}
			p.length = 0;
		}
		
		protected function gatherParameterValues(target:Object, targetType:Class, injector:Injector):Array
		{
			const len:int = _parameterMappingIDs.length;
			const parameters:Array = new Array(len);
			for (var i:int = 0; i < len; i++) 
			{
				const parameterMappingId:String = _parameterMappingIDs[i];
				const provider:IDependencyProvider = injector.IOCInternal::getProvider(parameterMappingId);
				if (!provider)
				{
					if (i >= _requiredParameters || _isOptional)
					{
						break;
					}
					throw new Error("gatherParameterValues" + (i + 1));
				}
				parameters[i] = provider.apply(targetType, injector, injectParameters);
			}
			return parameters;
		}
		
	}

}